package com.bham.teamwork.dao.impl;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.BatchUpdateUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import com.bham.teamwork.dao.BaseDao;

/**
 * 
 * 
 * @author RuJia Li
 * @author Federico Bacci
 * @author Alessandro Pozzer 
 * 
 */

@SuppressWarnings( { "rawtypes", "unchecked" })
public class BaseDaoImpl implements BaseDao {
	private NamedParameterJdbcOperations namedParameterJdbcOperations;
	private JdbcTemplate jdbcTemplate;

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	

	/**
	 * According to the complex connection SQL return to the entity list, query SQL need to add alias for each column, the format is as follows
	 * 
	 * @param strsql
	 * @param classstr
	 * @param clazz
	 * @return ObjectList
	 */
	public List getObjectListBySQL(final String strsql, final String classstr,
			final Class clazz) {
		return getObjectListBySQL(strsql, classstr, clazz, -1, -1, null);
	}

	/**
	 * According to the complex connection SQL return to the entity list, query SQL need to add alias for each column, the format is as follows
	 * 
	 * @param strsql
	 * @param classstr
	 * @param clazz
	 * @param params
	 * @return ObjectList
	 */
	public List getObjectListBySQL(final String strsql, final String classstr,
			final Class clazz, Object[] params) {
		return getObjectListBySQL(strsql, classstr, clazz, -1, -1, params);
	}

	/**
	 
	 * @param strsql
	 * @param classstr
	 * @param clazz
	 * @param pagenum
	 * @return ObjectList
	 */
	public List getObjectListBySQL(final String strsql, final String classstr,
			final Class clazz, final int pagenum, int pageSize) {
		return getObjectListBySQL(strsql, classstr, clazz, pagenum, -1, null);
	}

	/**
	 * Use Spring JDBC to obtain entity objects from SQL statements and parameter queries
	 * 
	 * @param sql
	 * @param rm
	 * @param args
	 * @throws Exception 
	 */
	public Object getObject(String sql, RowMapper rm, Object... args) {
		try {
			Object obj = jdbcTemplate.queryForObject(sql, rm, args);
			return obj;
		} catch (IncorrectResultSizeDataAccessException ex) {
			return null;
		}
	}

	/**
	 * Use Spring JDBC to get entity object List through SQL statement and parameter query
	 * @param sql
	 * @param rm
	 * @param args
	 * @return List
	 */
	public List getObjectList(String sql, RowMapper rm, Object... args) {
		return jdbcTemplate.query(sql, rm, args);
	}

	/**
	 * Use Spring JDBC to get entity object List through SQL statement and parameter paging query
	 * 
	 * @param sql
	 * @param rm
	 * @param pagenum
	 * @param pagesize
	 * @param args
	 * @return List
	 */
	public List getObjectList(String sql, RowMapper rm, int pagenum,
			int pagesize, Object... args) {
		int start = (pagenum - 1) * pagesize;
		int end = pagenum * pagesize;
		sql = "select * from (select alldata.*,rownum num from (" + sql
				+ ") alldata) where num>" + start + " and num<=" + end;
		return jdbcTemplate.query(sql, rm, args);
	}

	/**
	 * Use Spring JDBC to query single data Map through SQL statement and parameter
	 * @param sql
	 * @param args
	 * @return Map
	 */
	public Map<String, Object> getObjectMap(String sql, Object... args) {
		Map<String, Object> res = null;
		try {
			res = jdbcTemplate.queryForMap(sql, args);
		} catch (EmptyResultDataAccessException ex) {
			//ex.printStackTrace();
		}
		return res;
	}

	/**
	 * Use Spring JDBC to query multiple data Map through SQL statement and parameter
	 * 
	 * @param sql
	 * @param args
	 * @return Map List
	 */
	public List<Map<String, Object>> getObjectMapList(String sql,
			Object... args) {
		return jdbcTemplate.queryForList(sql, args);
	}

	public List<Map<String, Object>> getObjectMapList(String sql,int pagenum,
			int pagesize, Object... args) {
		int start = (pagenum - 1) * pagesize;
		int end = pagenum * pagesize;
		sql = "select * from (select alldata.*,rownum num from (" + sql
				+ ") alldata) where num>" + start + " and num<=" + end;
		return jdbcTemplate.queryForList(sql, args);
	}
	/**
	 * Using Spring JDBC through SQL statements and parameters for data updates, delete
	 * @param sql
	 * @param args
	 * @return flag
	 */
	public int updateExecute(String sql, Object... args) {
		return jdbcTemplate.update(sql, args);
	}

	/**
	 * Using Spring JDBC through SQL statements and parameters for data updates, delete
	 * @param sql
	 * @param param
	 * @return flag
	 */
	public int updateExecute(String sql, Map param) {
		return jdbcTemplate.update(sql, param);
	}

	public int[] updateExecute(String sql, List<Object[]> args) {
		//return jdbcTemplate.batchUpdate(sql, args);
		if (namedParameterJdbcOperations == null) {
			namedParameterJdbcOperations = new NamedParameterJdbcTemplate(getJdbcTemplate().getDataSource());
		}
		return BatchUpdateUtils.executeBatchUpdate(sql, args, new int[0], namedParameterJdbcOperations.getJdbcOperations());
	}

	public int[] updateExecute(String sql,
			BatchPreparedStatementSetter batchPreparedStatementSetter) {
		return jdbcTemplate.batchUpdate(sql, batchPreparedStatementSetter);
	}

	/**
	 * Use Spring JDBC to query the data Map through the SQL statement
	 * @param strsql
	 * @param obj
	 * @return Map
	 */
	public Map queryForMap(String strsql, Object... obj) {
		return jdbcTemplate.queryForMap(strsql, obj);
	}

	/**
	 * A 32-bit UUID is randomly generated
	 * 
	 * @return A 32-bit UUID 
	 */
	public String getUUID() {
		String s = UUID.randomUUID().toString();
		return s.substring(0, 8) + s.substring(9, 13) + s.substring(14, 18)
				+ s.substring(19, 23) + s.substring(24);
	}

	@Override
	public int[] batchUpdate(String[] sqls, Object... args) {
		return jdbcTemplate.batchUpdate(sqls);
	}


	@Override
	public List getObjectListBySQL(String strsql, String classstr, Class clazz,
			int pagenum, int pageSize, Object[] params) {
		// TODO Auto-generated method stub
		return null;
	}

}
